package com.chdz.code.utils;

import java.lang.reflect.Constructor;
import java.net.InetAddress;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.cluster.ClusterState;
import org.elasticsearch.cluster.metadata.IndexMetaData;
import org.elasticsearch.cluster.metadata.MappingMetaData;
import org.elasticsearch.common.settings.ImmutableSettings;
import org.elasticsearch.common.transport.InetSocketTransportAddress;
import com.chdz.code.model.ColumnClass;
import org.elasticsearch.common.settings.Settings;

/**
 * @Auther: Appet
 * @Date: 2018/8/6 16:00
 * @Description:
 */
public class ElasticSearchUtils {
    public static final String CLUSTER_NAME = "changhong-dev"; //实例名称
    private static final String IP = "192.168.10.210";
    private static final int PORT = 9300;  //端口
    private static String index = "areav1";
    private static String type = "areasearch";

    public static void main(String[] args) {
        System.out.println(getFieldsName(index, type));
    }

    public static Map<String, Object> getMapProperties(String indexname, String typename) {
        Map<String, Object> mapProperties = new HashMap<String, Object>();
        try {
            Settings settings = ImmutableSettings
                    .settingsBuilder()
                    .put("cluster.name", CLUSTER_NAME)
                    .put("client.transport.sniff", true)
                    .build();
            TransportClient client = null;
            try {
                Class<?> clazz = Class.forName(TransportClient.class.getName());
                Constructor<?> constructor = clazz.getDeclaredConstructor(org.elasticsearch.common.settings.Settings.class);
                constructor.setAccessible(true);
                client = (TransportClient) constructor.newInstance(settings);
                client.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName(IP), PORT));
            } catch (Exception e) {
                e.printStackTrace();
            }
            ClusterState cs = client.admin().cluster().prepareState()
                    .setIndices(indexname).execute().actionGet().getState();
            IndexMetaData imd = cs.getMetaData().index(indexname);
            MappingMetaData mdd = imd.mapping(typename);

            try {
                mapProperties = mdd.getSourceAsMap();
            } catch (Exception e) {
                e.printStackTrace();
            }
            if (client != null) {
                client.close();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return mapProperties;
    }
    public static Map<String,Map<String, List<ColumnClass>>> getFields(String indexname, String typename){
        Map<String, Object> mapProperties = ElasticSearchUtils.getMapProperties(indexname, typename);
        return getColumns(mapProperties);
    }

    public static Map<String,Map<String, List<ColumnClass>>> getColumns(Map<String, Object> mapProperties){
        Map<String,Map<String, List<ColumnClass>>> result = new HashMap<>();
        String[] fields = {"id","createBy","createTime","updateBy","updateTime","delFlag"};
        List<String> removeFields = Arrays.asList(fields);
        Map<String, Object> map = (Map<String, Object>) mapProperties.get("properties");
        Set<String> keys = map.keySet();
        List<ColumnClass> columnClassList = new ArrayList<>();
        List<ColumnClass> addUpdateResponse = new ArrayList<>();
        for(String key : keys){
            Map<String, Object> item = (Map<String, Object>) map.get(key);
            if(item.containsKey("type")){
                ColumnClass column = new ColumnClass();
                column.setColumnName(key);
                column.setColumnType(item.get("type").toString().toUpperCase());
                columnClassList.add(column);
                if(!removeFields.contains(key)){
                    addUpdateResponse.add(column);
                }
            }else{
                ColumnClass column = new ColumnClass();
                column.setColumnName(key);
                column.setColumnType("LIST");
                columnClassList.add(column);
                Map<String, Object> subItem = (Map<String, Object>) map.get(key);
                Map<String,Map<String, List<ColumnClass>>> subResult = getColumns(subItem);
                result.put(key,subResult.get("main"));
            }
        }
        Map<String, List<ColumnClass>> data = new HashMap<>();
        data.put("all",columnClassList);
        data.put("reduce",addUpdateResponse);
        result.put("main",data);
        return result;
    }
    /**
     * 功能描述：获取所有的字段
     * @param index
     * @param type
     * @return List<String>
     */
    public static List<String> getFieldsName(String index, String type) {
        Map<String, Object> mapProperties = ElasticSearchUtils.getMapProperties(index, type);
        List<String> fieldList = getIndexFieldList("", mapProperties);
        System.out.println("Field List:");
        for (String field : fieldList) {
            System.out.println(field);
        }
        return fieldList;
    }

    /**
     * 功能描述：分离出字段
     * @param fieldName
     * @param mapProperties
     * @return List<String>
     */
    public static List<String> getIndexFieldList(String fieldName,
                                                  Map<String, Object> mapProperties) {
        List<String> fieldList = new ArrayList<String>();
        Map<String, Object> map = (Map<String, Object>) mapProperties.get("properties");
        Set<String> keys = map.keySet();
        for (String key : keys) {
            if (((Map<String, Object>) map.get(key)).containsKey("type")) {
                fieldList.add(fieldName + "" + key);
            } else {
                List<String> tempList = getIndexFieldList(fieldName + "" + key
                        + ".", (Map<String, Object>) map.get(key));
                fieldList.addAll(tempList);
            }
        }
        return fieldList;
    }
}
